package com.jcfy.project.module.client;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.alibaba.fastjson.JSONArray;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jcfy.common.utils.bean.BeanUtils;
import com.jcfy.framework.base.ClientBaseController;
import com.jcfy.framework.base.Error;
import com.jcfy.framework.interceptor.annotation.RepeatSubmit;
import com.jcfy.framework.web.domain.AjaxResult;
import com.jcfy.project.module.domain.*;
import com.jcfy.project.module.domain.vo.CartsVo;
import com.jcfy.project.module.service.ITAccountService;
import com.jcfy.project.module.service.ITOrderGoodsService;
import com.jcfy.project.module.service.ITOrderService;
import com.jcfy.project.module.service.ITUserService;
import io.swagger.annotations.Api;
import jodd.util.StringUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

/**
 * 订单接口
 *
 * @author jiangfeng
 * @date 2020-08-13
 */
@Api("订单接口")
@RestController
@RequestMapping("/client/order")
public class OrderController extends ClientBaseController {

    @Value("${wx.pay.notifyUrl}")
    private String notifyUrl;
    @Resource
    private WxPayService wxPayService;
    @Autowired
    private WxMaService wxMaService;
    @Resource
    private ITOrderService orderService;
    @Resource
    private ITUserService userService;
    @Resource
    private ITAccountService accountService;
    @Resource
    private ITOrderGoodsService orderGoodsService;

    /**
     * 创建交易订单
     *
     * @param carts             购物车商品
     * @param team              提货信息
     * @param amount            订单金额
     * @param consigneeName     收货人姓名
     * @param consigneeMobile   收货人手机号
     * @param consigneeProvince 省份
     * @param consigneeCity     城市
     * @param consigneeArea     收货地址所在区
     * @param consigneeAddress  详细地址
     * @param remark            备注
     * @return
     */
    @RepeatSubmit   // 防止重复提交
    @PostMapping("/createOrder")
    public AjaxResult createOrder(String carts, String team, String amount, String consigneeName, String consigneeMobile, String consigneeProvince,
                                  String consigneeCity, String consigneeArea, String consigneeAddress, String remark) {
        Long userId = this.getSessionUserId();
        try {
            if (StringUtil.isBlank(carts)) {
                logger.error("[订单管理-创建订单][状态#失败][原因# 参数无效]");
                return AjaxResult.error(Error._100002);
            }

            TOrder order = null;
            //生成订单
            order = orderService.createOrder(carts, team, userId, amount, consigneeName, consigneeMobile, consigneeProvince,
                    consigneeCity, consigneeArea, consigneeAddress, remark);
            if (order == null) {
                logger.error("[订单管理-创建订单][状态#失败][原因# 订单创建失败]");
                return AjaxResult.error(Error._200401);
            }
            Map<String, Object> map = new HashMap<>();
            //订单流水号
            map.put("traceNo", order.getTraceNo());
            DecimalFormat df = new DecimalFormat("#0.00");
            //订单总金额
            map.put("amount", df.format(order.getAmount()));
            //订单id
            map.put("orderId", order.getOrderId());
            AjaxResult result = AjaxResult.success();
            result.put("data", map);
            return result;
        } catch (Exception e) {
            logger.error("[订单管理-创建订单][状态#异常][原因# " + e.getMessage() + "]", e);
            return AjaxResult.error(Error._100000, e.getMessage());
        }
    }

    /**
     * 发起与支付
     * 调用统一下单接口，获取“预支付交易会话标识”
     *
     * @param traceNo 订单号
     * @param amount  订单金额
     * @return
     */
    @RepeatSubmit
    @PostMapping("/smallRoutinePay")
    public AjaxResult smallRoutinePay(String traceNo, String amount) {
        try {
            TUser user = this.getSessionUser();
            if (user == null) {
                logger.info("[订单管理-微信小程序支付][状态#失败][原因:未登录或会话已超时]");
                return AjaxResult.error(Error._100001);
            }

            // 调用统一生成订单接口
            WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
            orderRequest.setSignType(WxPayConstants.SignType.MD5);
            orderRequest.setBody("商品团购订单");
            orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
            orderRequest.setOutTradeNo(traceNo); //自己生成订单号
            BigDecimal totalFee = new BigDecimal(amount);
            orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(totalFee.toString()));//直接分
            orderRequest.setOpenid(user.getMiniOpenid()); // 获取微信支付用户的openId
            orderRequest.setSpbillCreateIp(this.getIpAddress(request)); //请求主机IP地址
            Date now = new Date();
            Date afterDate = DateUtils.addMinutes(now, 10);//10分钟后
            orderRequest.setTimeStart(DateFormatUtils.format(now, "yyyyMMddHHmmss"));
//            orderRequest.setTimeExpire(DateFormatUtils.format(afterDate, "yyyyMMddHHmmss"));
            orderRequest.setNotifyUrl(notifyUrl);
            Object order = wxPayService.createOrder(orderRequest);
            logger.info("[订单管理-微信小程序支付][状态#成功]");
            AjaxResult result = AjaxResult.success();
            result.put("data", order);
            return result;
        } catch (Exception e) {
            logger.error("[订单管理-微信小程序支付][状态#异常][原因# " + e.getMessage() + "]", e);
            return AjaxResult.error(Error._100000, e.getMessage());
        }
    }

    /**
     * 微信支付回调地址
     */
    @PostMapping("/payNotifyUrl")
    public String payNotifyUrl(HttpServletRequest request, HttpServletResponse response) {
        try {
            String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
            WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlResult);
            if ("SUCCESS".equals(notifyResult.getResultCode())) {
                logger.info("[订单管理-微信小程序支付回调][状态#成功]");
                // 商户单号(本系统)
                String traceNo = notifyResult.getOutTradeNo();
                // 微信交易单号
                String payNo = notifyResult.getTransactionId();
                String openId = notifyResult.getOpenid();
                logger.info("【openId】:" + openId);
                logger.info("【traceNo】:" + traceNo);
                logger.info("【payNo】:" + payNo);
                // 支付成功后，更新订单信息
                Integer payType = 1;// 微信小程序支付
                TOrder order = orderService.paySuccess(traceNo, payType, openId, payNo);
            }
            //自己处理订单的业务逻辑，需要判断订单是否已经支付过，否则可能会重复调用
            return WxPayNotifyResponse.success("成功");
        } catch (Exception e) {
            logger.error("[订单管理-微信小程序支付回调][状态#异常][原因# " + e.getMessage() + "]", e);
            return WxPayNotifyResponse.success("code:" + 9999 + "微信回调结果异常,异常原因:" + e.getMessage());
        }
    }

    /**
     * 订单列表
     *
     * @param order
     * @param pageNum
     * @param pageSize
     * @return
     */
    @PostMapping("/list")
    public AjaxResult list(TOrder order, Integer pageNum, Integer pageSize) {
        Long userId = this.getSessionUserId();
        try {
            PageHelper.startPage(pageNum, pageSize);
            order.setUserId(userId);
            List<TOrder> list = orderService.selectTOrderList(order);
            PageInfo<Object> pageInfo = new PageInfo(list);
            List<Object> orderList = new ArrayList<>();
            list.forEach(item -> {
                Map<String, Object> orderMap = BeanUtils.bean2Map(item);
                List<TOrderGoods> orderGoodsList = orderGoodsService.selectTOrderGoodsList(new TOrderGoods(item.getOrderId(), 0));
                List<Object> cartsList = new ArrayList<>();
                orderGoodsList.forEach(orderGoods -> {
                    Map<String, Object> cartsMap = new HashMap<>();
                    cartsMap.put("count", orderGoods.getNumber());
                    cartsMap.put("goods", orderGoods);
                    cartsList.add(cartsMap);
                });
                orderMap.put("carts", cartsList);
                orderList.add(orderMap);
            });
            pageInfo.setList(orderList);
            return AjaxResult.success(pageInfo);
        } catch (Exception e) {
            logger.error("[订单管理-订单列表][状态#异常][原因# " + e.getMessage() + "]", e);
            return AjaxResult.error(Error._100000, e.getMessage());
        }
    }

}
